home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / unix / c / wait4 < prev    next >
Text File  |  1996-11-09  |  4KB  |  153 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/unix/c/RCS/wait4,v $
  4.  * $Date: 1996/10/30 22:04:51 $
  5.  * $Revision: 1.2 $
  6.  * $State: Rel $
  7.  * $Author: unixlib $
  8.  *
  9.  * $Log: wait4,v $
  10.  * Revision 1.2  1996/10/30 22:04:51  unixlib
  11.  * Massive changes made by Nick Burret and Peter Burwood.
  12.  *
  13.  * Revision 1.1  1996/05/06 09:03:14  unixlib
  14.  * Initial revision
  15.  *
  16.  ***************************************************************************/
  17.  
  18. static const char rcs_id[] = "$Id: wait4,v 1.2 1996/10/30 22:04:51 unixlib Rel $";
  19.  
  20. #include <unixlib/types.h>
  21. #include <sys/wait.h>
  22. #include <sys/resource.h>
  23. #include <sys/unix.h>
  24. #include <errno.h>
  25. #include <stdlib.h>
  26.  
  27. /* If usage is not null, wait4 returns usage figures for the child
  28.    process in *usage (but only if the child has terminated and not
  29.    if it has stopped).  */
  30.  
  31. /* wait, wait3 and wait4 are all derivatives of the function, waitpid.
  32.    waitpid has been implemented through wait4 for practical reasons.
  33.  
  34.    The waitpid function is used to request status information from
  35.    a child process whose process ID is pid.  Normally, the calling
  36.    process is suspended until the child process makes status information
  37.    available by terminating.
  38.  
  39.    Error conditions:
  40.  
  41.    EINTR: The function was interrupted by delivery of a signal to the
  42.    calling process.
  43.  
  44.    ECHILD: There are no child processes to wait for, or the specified pid
  45.    is not a child of the calling process.
  46.  
  47.    EINVAL: An invalid value was provided for the options argument.
  48.  
  49.    Symbolic constants (through pid):
  50.  
  51.    WAIT_ANY: Value is -1 and specifies that waitpid should return status
  52.    information about any child process.
  53.  
  54.    WAIT_MYPGRP: Value is 0 and specifies that waitpid should return
  55.    status information about any child process in the same process group
  56.    as the calling process.
  57.  
  58.    Symbolic constants (passed through options):
  59.  
  60.    WNOHANG: waitpid should return immediately instead of waiting, if
  61.    there is no child process ready to be noticed.
  62.  
  63.    WUNTRACED: waitpid should report the status of any child processes
  64.    that have been stopped as well as those that have terminated.  */
  65.  
  66. /* Make conversion of the process exit status easy done.  */
  67.  
  68. static int
  69. wait_convert_status (struct __process *status)
  70. {
  71.   if (status->signal_exit)
  72.     return __W_EXITCODE (status->return_code, status->signal);
  73.   if (status->core_dump)
  74.     return __WCOREFLAG;
  75.   if (status->stopped)
  76.     return __W_STOPCODE (status->signal);
  77.  
  78.   return __W_EXITCODE (status->return_code, 0);
  79. }
  80.  
  81. /* Make the process of comparing process IDs fairly easy.  */
  82. static int
  83. wait_type (__pid_t pid, int p)
  84. {
  85.   /* Match any process.  */
  86.   if (pid == WAIT_ANY)
  87.     return 1;
  88.   /* Match any process in the current process's group.  */
  89.   if (pid == WAIT_MYPGRP)
  90.     if (__u->child[p].gid == __u->gid)
  91.       return 1;
  92.   /* Match any process whose process group is the abs(pid).  */
  93.   if (pid < -1)
  94.     if (__u->child[p].gid == abs (pid))
  95.       return 1;
  96.   /* Match a specific process id.  */
  97.   if (__u->child[p].pid == pid)
  98.     return 1;
  99.  
  100.   /* No match found.  */
  101.   return 0;
  102. }
  103.  
  104.  
  105. __pid_t
  106. wait4 (__pid_t pid, int *status, int options, struct rusage *usage)
  107. {
  108.   static int process = 0;
  109.   int start_value;
  110.  
  111.   if (options < 0 || options > (WNOHANG + WUNTRACED))
  112.     {
  113.       errno = EINVAL;
  114.       return (__pid_t)-1;
  115.     }
  116.  
  117.   start_value = process;
  118.   while (1)
  119.     {
  120.       if (wait_type (pid, process))
  121.     if (!__u->child[process].status.stopped
  122.         || ((options & WUNTRACED) && __u->child[process].status.stopped))
  123.       {
  124.         /* If the untraced bit is set, we will match against
  125.            stopped children; otherwise we won't.  */
  126.  
  127.         /* Copy the resource usage details (if usage is not null).  */
  128.         if (usage && __u->child[process].pid == pid)
  129.           *usage = __u->child[process].usage;
  130.         if (status)
  131.           {
  132.             *status = wait_convert_status (&__u->child[process].status);
  133. #ifdef DEBUG
  134.                 printf ("wait4: process = %d, status = %x\n", process, *status);
  135. #endif
  136.           }
  137.         return __u->child[process].pid;
  138.       }
  139.  
  140.       if (++process == CHILD_MAX)
  141.     process = 0;
  142.  
  143.       /* If the no hang bit is set and we have found no dead
  144.          children, return 0.  */
  145.       if ((options & WNOHANG) && process == start_value)
  146.     {
  147.       errno = ECHILD;
  148.       return (__pid_t)0;
  149.     }
  150.     };
  151.   return (__pid_t)-1;
  152. }
  153.